Skip to content

Conversation

@WarningImHack3r
Copy link
Owner

@WarningImHack3r WarningImHack3r commented May 3, 2025

Fixes #57

Quite self-explanatory: add RSS feeds for each package and all packages at once.

All feeds are available as RSS 2 (/rss.xml), ATOM (/atom.xml), and JSON Feed (/rss.json). As described, they're accessible by appending the appropriate suffix to their regular URL (e.g., /package/svelte/rss.xml).

Similarly, RSS feeds for all the packages are available under /package/all/rss.xml and equivalents.

Roadmap

  • Add per-package feeds
  • Add a UI button on the package page redirecting to the feeds
  • Add global, all-packages RSS feed
    • This will lay the foundation for an "all packages" page
    • As the page doesn't yet exist, the feed URL won’t be documented yet either

References

Summary by CodeRabbit

  • New Features

    • Added animated collapsible content component for enhanced UI interactions.
    • Introduced an interactive RSS feed selector in the package page header, allowing users to choose between XML, Atom, and JSON formats for package release feeds.
    • Added new endpoints to provide RSS, Atom, and JSON feeds for package releases.
    • Enabled retrieval of all package releases across categories in a consolidated view.
  • Chores

    • Updated dependencies and added new development tools to support feed generation and Markdown processing.

@WarningImHack3r WarningImHack3r self-assigned this May 3, 2025
@vercel
Copy link

vercel bot commented May 3, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
svelte-changelog ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 4, 2025 9:30pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented May 3, 2025

Walkthrough

This change introduces RSS feed support for package releases. New server endpoints are added to serve package-specific RSS feeds in XML, Atom, and JSON formats. A utility function is implemented to generate feeds for either a single package or all packages. The UI for package pages is updated to include a collapsible RSS feed selector, allowing users to access the different feed formats. Supporting dependencies for feed generation and Markdown parsing are added. Additionally, a helper function is introduced to fetch and aggregate releases for all packages.

Changes

File(s) Change Summary
package.json Updated @tailwindcss/vite and tailwindcss dependencies; added feed and marked as dev dependencies.
src/lib/components/AnimatedCollapsibleContent.svelte Added new Svelte component for animated collapsible content, used for smooth UI transitions.
src/routes/package/[...package]/+page.svelte Enhanced package page header with a collapsible RSS feed selector UI, including buttons for XML, Atom, and JSON feeds.
src/routes/package/[...package]/atom.xml/+server.ts
src/routes/package/[...package]/rss.json/+server.ts
src/routes/package/[...package]/rss.xml/+server.ts
Added new GET request handlers to serve Atom, JSON, and XML RSS feeds for packages, using a shared feed generation utility.
src/routes/package/[...package]/rss.ts Implemented rssHandler utility to generate and serve RSS feeds for single or all packages, supporting multiple formats and Markdown-to-HTML conversion.
src/routes/package/releases.ts Added function to aggregate and sort releases from all packages for consolidated feeds.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant UI (Package Page)
    participant Server (SvelteKit)
    participant RSS Handler
    participant Feed Generator
    participant Data Source

    User->>UI (Package Page): Clicks RSS feed button
    UI (Package Page)->>Server (SvelteKit): Requests /package/[...package]/rss.xml (or .json/.xml/.atom)
    Server (SvelteKit)->>RSS Handler: Handles GET request
    RSS Handler->>Feed Generator: Fetch package/all releases, build feed
    Feed Generator->>Data Source: Retrieve release data
    Data Source-->>Feed Generator: Return release info
    Feed Generator-->>RSS Handler: Return feed object
    RSS Handler-->>Server (SvelteKit): Format feed (XML/JSON/Atom)
    Server (SvelteKit)-->>UI (Package Page): Respond with feed content
    UI (Package Page)-->>User: Feed is available for subscription
Loading

Assessment against linked issues

Objective Addressed Explanation
Add package-specific RSS feeds to package routes (#57)
Add a consolidated RSS feed to the homepage (#57) No endpoint or code for a homepage/global RSS feed is present in this change.

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

src/routes/package/[...package]/+page.svelte

Oops! Something went wrong! :(

ESLint: 9.25.1

Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@sveltejs/adapter-vercel' imported from /svelte.config.js
at packageResolve (node:internal/modules/esm/resolve:839:9)
at moduleResolve (node:internal/modules/esm/resolve:908:18)
at defaultResolve (node:internal/modules/esm/resolve:1038:11)
at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:557:12)
at ModuleLoader.resolve (node:internal/modules/esm/loader:525:25)
at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:246:38)
at ModuleJob._link (node:internal/modules/esm/module_job:126:49)

src/lib/components/AnimatedCollapsibleContent.svelte

Oops! Something went wrong! :(

ESLint: 9.25.1

Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@sveltejs/adapter-vercel' imported from /svelte.config.js
at packageResolve (node:internal/modules/esm/resolve:839:9)
at moduleResolve (node:internal/modules/esm/resolve:908:18)
at defaultResolve (node:internal/modules/esm/resolve:1038:11)
at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:557:12)
at ModuleLoader.resolve (node:internal/modules/esm/loader:525:25)
at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:246:38)
at ModuleJob._link (node:internal/modules/esm/module_job:126:49)

src/routes/package/[...package]/atom.xml/+server.ts

Oops! Something went wrong! :(

ESLint: 9.25.1

Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@sveltejs/adapter-vercel' imported from /svelte.config.js
at packageResolve (node:internal/modules/esm/resolve:839:9)
at moduleResolve (node:internal/modules/esm/resolve:908:18)
at defaultResolve (node:internal/modules/esm/resolve:1038:11)
at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:557:12)
at ModuleLoader.resolve (node:internal/modules/esm/loader:525:25)
at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:246:38)
at ModuleJob._link (node:internal/modules/esm/module_job:126:49)

  • 4 others
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@WarningImHack3r WarningImHack3r marked this pull request as ready for review May 4, 2025 21:30
@WarningImHack3r WarningImHack3r changed the title feat!: add RSS feeds feat: add RSS feeds May 4, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (5)
src/lib/components/AnimatedCollapsibleContent.svelte (1)

1-32: Clean implementation of animated collapsible content.

This component effectively extends the bits-ui Collapsible.Content with smooth slide transitions and follows Svelte 5 patterns correctly.

Consider making the flex class configurable to increase component flexibility:

- <div {...props} transition:slide={{ duration, axis }} class="flex">
+ <div {...props} transition:slide={{ duration, axis }} class={`flex ${$$props.class || ''}`}>

Also, note that using forceMount always keeps the content in the DOM, which might impact performance for complex content. This is typically a reasonable tradeoff for smoother animations, but worth being aware of for future reference.

src/routes/package/[...package]/atom.xml/+server.ts (1)

1-11: Consider using more specific content type for Atom feeds.

The implementation is clean and consistent with other feed endpoints.

For Atom feeds, the more specific MIME type application/atom+xml is widely recognized and preferred over generic application/xml:

  text(feed.atom1(), {
    headers: {
      "Cache-Control": "max-age=0, s-max-age=600",
-     "Content-Type": "application/xml"
+     "Content-Type": "application/atom+xml"
    }
  })
src/routes/package/[...package]/+page.svelte (1)

71-112: UI improvements look good, but check URL concatenation

The RSS feed selector UI is well-implemented with proper accessibility considerations and animations. However, there's a potential issue with the URL construction that could lead to malformed URLs.

The URL construction on line 105 might result in double slashes if the page URL already ends with a slash. Consider using a more robust URL joining approach:

-									href="{page.url}/{file}"
+									href="{page.url.endsWith('/') ? page.url + file : `${page.url}/${file}`}"
src/routes/package/[...package]/rss.ts (2)

14-35: The base feed configuration looks good, but URL handling could be improved

The getBaseFeed function sets up a well-structured feed with all the necessary metadata. However, the URL manipulation for feed links is using regex replacement which might be fragile.

Consider using URL manipulation methods instead of regex for more robust URL handling:

-			xml: url.toString().replace(/[A-z\d]+\.[A-z\d]+$/, "rss.xml"),
-			json: url.toString().replace(/[A-z\d]+\.[A-z\d]+$/, "rss.json"),
-			atom: url.toString().replace(/[A-z\d]+\.[A-z\d]+$/, "atom.xml")
+			xml: new URL("rss.xml", url.origin + url.pathname.replace(/[^/]+$/, "")).toString(),
+			json: new URL("rss.json", url.origin + url.pathname.replace(/[^/]+$/, "")).toString(),
+			atom: new URL("atom.xml", url.origin + url.pathname.replace(/[^/]+$/, "")).toString()

42-46: Consider sanitization for Markdown content

While GitHub content might be trusted, it's generally a good practice to sanitize HTML output from markdown converters.

Even though you're handling GitHub content which is likely safe, it might be worth adding sanitization for extra security. The marked library has sanitization options that can be enabled.

-	// we'll assume GH content doesn't need to be sanitized *wink wink*
-	return marked(md) as string; // can only be a Promise if the `async` option is set to true, not the case here
+	// Enable sanitization for extra security
+	return marked(md, { sanitize: true }) as string; // can only be a Promise if the `async` option is set to true, not the case here

Or consider using DOMPurify as an additional layer:

import DOMPurify from 'dompurify';
// ...
return DOMPurify.sanitize(marked(md) as string);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c6fe0a4 and 71875bc.

⛔ Files ignored due to path filters (2)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • src/lib/components/ui/collapsible/index.ts is excluded by !src/lib/components/ui/**
📒 Files selected for processing (8)
  • package.json (3 hunks)
  • src/lib/components/AnimatedCollapsibleContent.svelte (1 hunks)
  • src/routes/package/[...package]/+page.svelte (2 hunks)
  • src/routes/package/[...package]/atom.xml/+server.ts (1 hunks)
  • src/routes/package/[...package]/rss.json/+server.ts (1 hunks)
  • src/routes/package/[...package]/rss.ts (1 hunks)
  • src/routes/package/[...package]/rss.xml/+server.ts (1 hunks)
  • src/routes/package/releases.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: WarningImHack3r
PR: WarningImHack3r/svelte-changelog#56
File: src/routes/package/+layout.server.ts:28-40
Timestamp: 2025-04-25T10:58:24.062Z
Learning: WarningImHack3r prefers elegant, aesthetically pleasing solutions for performance optimizations rather than quick fixes that introduce nested async IIFEs or similar approaches that might make code harder to read.
Learnt from: WarningImHack3r
PR: WarningImHack3r/svelte-changelog#48
File: src/routes/package/[...package]/+page.server.ts:50-53
Timestamp: 2025-04-11T10:33:07.002Z
Learning: WarningImHack3r prefers to keep server-side console.log statements in the codebase as they find them useful for debugging and monitoring, even if they might clean them up later.
🧬 Code Graph Analysis (3)
src/routes/package/[...package]/atom.xml/+server.ts (3)
src/routes/package/[...package]/rss.json/+server.ts (1)
  • GET (4-11)
src/routes/package/[...package]/rss.xml/+server.ts (1)
  • GET (4-11)
src/routes/package/[...package]/rss.ts (1)
  • rssHandler (53-106)
src/routes/package/[...package]/rss.json/+server.ts (1)
src/routes/package/[...package]/rss.ts (1)
  • rssHandler (53-106)
src/routes/package/releases.ts (1)
src/lib/server/package-discoverer.ts (1)
  • discoverer (150-150)
🔇 Additional comments (4)
package.json (1)

31-31: LGTM: TailwindCSS dependencies updated.

The minor version updates to TailwindCSS dependencies are appropriate.

Also applies to: 63-63

src/routes/package/[...package]/rss.json/+server.ts (1)

1-11: Looks good - JSON feed implementation is clean and concise

The JSON feed implementation follows SvelteKit's conventions, reuses the shared rssHandler, and sets appropriate headers for content type and caching strategy.

src/routes/package/[...package]/rss.xml/+server.ts (1)

1-11: Looks good - XML feed implementation is clean and concise

The XML feed implementation follows SvelteKit's conventions, reuses the shared rssHandler, and sets appropriate headers for content type and caching strategy.

src/routes/package/[...package]/rss.ts (1)

53-106:

✅ Verification successful

RSS handler implementation is solid with good error handling

The rssHandler function is well-implemented with proper error handling, support for both single package and all packages, and comprehensive feed generation. It also aligns with your preference for clean, readable code as seen in previous PRs.


🏁 Script executed:

#!/bin/bash
# Verify consistent case-handling for package slugs

# Check if there are other places in the codebase where slugs are compared
rg -C 3 "package(Name|Slug)\.toLowerCase\(\)"

Length of output: 503


Approve: RSS handler is solid and slug case-handling is consistent

I’ve verified that the only case-insensitive comparison (slugPackage.toLowerCase() === "all") is correctly scoped to this handler and there are no other slug or package-name comparisons elsewhere in the codebase. The implementation is clean, has proper error handling, and generates the feed as expected. Great work!

@WarningImHack3r WarningImHack3r merged commit 22f651f into main May 4, 2025
5 checks passed
@WarningImHack3r WarningImHack3r deleted the rss-feeds branch May 4, 2025 21:48
@coderabbitai coderabbitai bot mentioned this pull request Oct 7, 2025
7 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add RSS feeds

2 participants